package com.hyt.it.ogt.ykcj.service.grade.impl;

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import com.hyt.it.ogt.ykcj.common.core.domain.entity.SysUser;
import com.hyt.it.ogt.ykcj.common.enums.BizErrorCode;
import com.hyt.it.ogt.ykcj.common.exception.CustomException;
import com.hyt.it.ogt.ykcj.common.utils.SecurityUtils;
import com.hyt.it.ogt.ykcj.domain.grade.ExamineeGradeInfo;
import com.hyt.it.ogt.ykcj.domain.vo.ExamSubjectVo;
import com.hyt.it.ogt.ykcj.domain.vo.ImportGradeInfoVo;
import com.hyt.it.ogt.ykcj.mapper.exam.ExamSubjectInfoMapper;
import com.hyt.it.ogt.ykcj.mapper.exam.ExamSubjectNameConfigMapper;
import com.hyt.it.ogt.ykcj.mapper.grade.ExamineeGradeInfoMapper;
import com.hyt.it.ogt.ykcj.service.exam.IChangedExamInfoService;
import com.hyt.it.ogt.ykcj.service.grade.IExamineeGradeInfoService;
import com.hyt.it.ogt.ykcj.service.grade.ImportAbstractService;

/**
 * @Author chentb
 * @Date 2021/6/22 13:57
 */
@Service
public class ImportExcelGradeServiceImpl extends ImportAbstractService {

    private static final Logger log = LoggerFactory.getLogger(ImportExcelGradeServiceImpl.class);

    @Autowired
    private ExamineeGradeInfoMapper gradeInfoMapper;

    @Autowired
    private ExamSubjectNameConfigMapper subjectNameConfigMapper;

    @Autowired
    private IExamineeGradeInfoService gradeInfoService;

    @Autowired
    private ExamSubjectInfoMapper subjectInfoMapper;

    @Autowired
    IChangedExamInfoService changedExamInfoService;

    @Transactional(rollbackFor={RuntimeException.class})
    @Override
    public List<ImportGradeInfoVo> importFile(MultipartFile multipartFile, String examId, String examNameConfigId, String examYear) {
        log.info("导入成绩begin...文件类型为excel文件");
        long startTime = System.currentTimeMillis();
        FileInputStream fis = null;
        List<ImportGradeInfoVo> list = new ArrayList<>();
        Workbook wb =null;
        try {
            String[] split = multipartFile.getOriginalFilename().split("\\.");  //.是特殊字符，需要转义！！！！！

            File file = null;
            String originalFilename = multipartFile.getOriginalFilename();
            String[] filename = originalFilename.split("\\.");
            file= File.createTempFile(filename[0], filename[1]);
            multipartFile.transferTo(file);
            file.deleteOnExit();
            fis = new FileInputStream(file);// 文件流对象
            //根据文件后缀（xls/xlsx）进行判断
            if ( "xls".equals(split[1])){
                wb = new HSSFWorkbook(fis);
            }else if ("xlsx".equals(split[1])){
                wb = new XSSFWorkbook(fis);
            }else {
                throw new CustomException("文件类型错误");
            }

            //开始解析
            Sheet sheet = wb.getSheetAt(0);     //读取sheet 0
            int headRowIndex = sheet.getFirstRowNum();
            Row headRow = sheet.getRow(headRowIndex);
            int subjectNum = 0;
            // 获取所有的字段名称,并通过字段名称判断有多少个科目成绩
            String[] fieldName = null;
            if (null != headRow){
                int firstCellIndex = headRow.getFirstCellNum();
                int lastCellIndex = headRow.getLastCellNum();
                fieldName = new String[lastCellIndex];
                for (int cIndex = firstCellIndex; cIndex < lastCellIndex; cIndex++) {   //遍历列
                    Cell cell = headRow.getCell(cIndex);
                    if (cell != null) {
                        fieldName[cIndex] = cell.toString();
                        if (fieldName[cIndex].contains(PREFIX_KM)){
                            subjectNum ++;
                        }
                    }
                }
            }

            List<ExamSubjectVo> subjectVoList = subjectInfoMapper.selectExamSubjectInfoByExamId(examId);
            if (subjectNum != subjectVoList.size()){
                throw new CustomException(BizErrorCode.GRADE_E0009);
            }
            // 获取当前登录用户
            SysUser sysUser = SecurityUtils.getLoginUser().getUser();
            list = readImportFile(list,sheet,subjectNum,fieldName,sysUser,examId,examNameConfigId,examYear);
        }catch (Exception e){
            log.error("导入成绩信息出现异常",e);
            throw new CustomException("导入成绩信息出现异常");
        } finally {
            try {
                if(null != fis){
                    fis.close();
                    log.info("文件流关闭成功");
                }
                if(null != wb){
                    wb.close();
                }

            } catch (Exception e) {
                log.info("文件流关闭失败！:{}",e);
            }
        }

        long endTime = System.currentTimeMillis();
        log.info("导入成绩结束,共耗时{}秒",(endTime-startTime)/1000);
        return list;
    }




    /**
     * 读取导入文件数据
     * @param list
     * @param sheet
     * @param subjectNum
     * @param fieldName
     * @param sysUser
     * @param examId
     * @param examNameConfigId
     * @param examYear
     * @return
     * @throws Exception
     */
    private List<ImportGradeInfoVo> readImportFile(List<ImportGradeInfoVo> list, Sheet sheet, int subjectNum, String[] fieldName, SysUser sysUser, String examId, String examNameConfigId, String examYear) throws Exception{
        // 取出字段信息
        Object[] rowValues =new Object[fieldName.length];
        //存放错误信息
        List<ImportGradeInfoVo> errorlist = new ArrayList<>();
        // 数据是否校验通过
        boolean flag = true;

        // 已存在的考生列表
        ExamineeGradeInfo examineeGradeInfo = new ExamineeGradeInfo();
        examineeGradeInfo.setExamId(examId);
        List<ExamineeGradeInfo> gradeInfoList = gradeInfoMapper.selectExamineeGradeInfoList(examineeGradeInfo);
        Map<String,ExamineeGradeInfo> gradeInfoMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(gradeInfoList)){
            gradeInfoMap = gradeInfoList.stream().collect(Collectors.toMap(ExamineeGradeInfo::getExamineeIdCode,gradeInfo->gradeInfo));
        }

        // 考试科目列表
        List<ExamSubjectVo> nameList = subjectInfoMapper.selectExamSubjectInfoByExamId(examId);
        Map<String,String> subjectNameMap = new HashMap<>();
        List<String> subjcetCodeList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(nameList)){
            subjectNameMap = nameList.stream().collect(Collectors.toMap(ExamSubjectVo::getSubjectNameCode,ExamSubjectVo::getSubjectId));
            subjcetCodeList = nameList.stream().map(ExamSubjectVo::getSubjectNameCode).collect(Collectors.toList());
        }
        // 读取execl数据
        int firstRowIndex = sheet.getFirstRowNum()+1;   //第一行是列名，所以不读
        int lastRowIndex = sheet.getLastRowNum();
        for(int rIndex = firstRowIndex; rIndex <= lastRowIndex; rIndex++) {   //遍历行
            Row row = sheet.getRow(rIndex);
            if (row != null) {
                for (int cIndex = 0; cIndex < fieldName.length; cIndex++) {   //遍历列
                    rowValues[cIndex]= row.getCell(cIndex);
                }
                ImportGradeInfoVo gradeInfoVo = new ImportGradeInfoVo();
                setGradeInfo(gradeInfoVo,subjcetCodeList,fieldName,rowValues,sysUser,examId,gradeInfoMap,subjectNameMap,examYear,rIndex+1);
                if (!StringUtils.isEmpty(gradeInfoVo.getErrorMsg())){
                    flag = false;
                    errorlist.add(gradeInfoVo);
                    continue;
                }
                list.add(gradeInfoVo);

            }
        }

        //flag为false则返回errorlist
        if(!flag){
            return errorlist;
        }

        // list不为空则执行插入
        if (!CollectionUtils.isEmpty(list)){
            batchInsertGrade(list);
            // 插入需要变更的考试信息
            changedExamInfoService.addChangedExamInfo(examineeGradeInfo.getExamId());
            //gradeInfoService.insertGradeInfo(list);
        }
        return null;
    }

}
